package com.axxc.cloud.es.index;

import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.highlight.HighlightField;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import com.axxc.cloud.es.index.document.ArticleDemo;
import com.axxc.cloud.es.index.repository.IArticleDemoRepository;
import com.fasterxml.jackson.databind.ObjectMapper;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class IndexDemo {

	private Client client;

	@Before
	public void buildClient() throws Exception {

		client = TransportClient.builder().build()
				.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
	}

	@Test
	public void buildIndex() {
		client.admin().indices().prepareCreate("article").get();
	}

	@Test
	public void indexDelete() {
		client.admin().indices().prepareDelete("article").get();
	}

	@Test
	public void buildMapper() throws Exception {

		XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("article")
				.startObject("properties").startObject("id").field("type", "integer").field("store", "yes").endObject()
				.startObject("title").field("type", "string").field("store", "yes").field("analyzer", "ik").endObject()
				.startObject("content").field("type", "string").field("store", "yes").field("analyzer", "ik")
				.endObject().endObject().endObject().endObject();
		PutMappingRequest mappingRequest = Requests.putMappingRequest("article").type("article")
				.source(xContentBuilder);

		client.admin().indices().putMapping(mappingRequest).get();

		client.close();

	}

	@Test
	public void buildDocument() throws Exception {

		Article article;
		for (int i = 0; i < 30; i++) {
			article = new Article();
			article.setId(String.valueOf(i));
			article.setTitle(i + "测试ES搜索引擎及IK分词器" + DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
			article.setContent(i + "今天基于ES原生语法测试操作ES索引库的增删改查及案例demo");

			client.prepareIndex("article", "article", article.getId())
					.setSource(new ObjectMapper().writeValueAsString(article)).get();
		}
	}

	@Test
	public void updateDocument1() throws Exception {
		Article article = new Article();
		article.setId("1");
		article.setTitle("测试ES搜索引擎及IK分词器-2018年5月22日23:16:35");
		article.setContent("测试文档的修改");

		client.prepareUpdate("article", "article", article.getId())
				.setDoc(new ObjectMapper().writeValueAsString(article)).get();
	}

	@Test
	public void updateDocument2() throws Exception {
		Article article = new Article();
		article.setId("1");
		article.setTitle("测试ES搜索引擎及IK分词器-2018年5月22日23:16:35");
		article.setContent("测试文档的修改");

		client.update(new UpdateRequest("article", "article", article.getId())
				.doc(new ObjectMapper().writeValueAsString(article))).get();
	}

	@Test
	public void deleteDocument1() throws Exception {
		Article article = new Article();
		article.setId("1");

		client.prepareDelete("article", "article", article.getId()).get();
	}

	@Test
	public void deleteDocument2() throws Exception {
		Article article = new Article();
		article.setId("2");

		client.delete(new DeleteRequest("article", "article", article.getId())).get();
	}

	@Test
	public void pageSearchDocument1() throws Exception {

		SearchResponse searchResponse = client.prepareSearch("article").setTypes("article")
				.setQuery(QueryBuilders.matchAllQuery()).setFrom(0)// 分页参数,从0开始
				.setSize(15)// 每页条数,默认10
				.get();
		SearchHits hits = searchResponse.getHits();// 命中
		System.out.println("命中条数" + hits.getTotalHits());
		for (SearchHit searchHit : hits) {
			System.out.println(searchHit.getSource().get("title"));
		}

	}

	@Test
	public void pageSearchDocument2() throws Exception {

		SearchResponse searchResponse = client.prepareSearch("article").setTypes("article")
				.setQuery(QueryBuilders.wildcardQuery("title", "分词器")).setFrom(0)// 分页参数,从0开始
				.setSize(15)// 每页条数,默认10
				.get();
		SearchHits hits = searchResponse.getHits();// 命中
		System.out.println("命中条数" + hits.getTotalHits());
		for (SearchHit searchHit : hits) {
			System.out.println(searchHit.getSource().get("title"));
		}

	}

	@Test
	public void pageSearchDocumentAndHighLight() throws Exception {

		SearchResponse searchResponse = client.prepareSearch("article").setTypes("article")
				.setQuery(QueryBuilders.termQuery("title", "分词")).setFrom(0)// 分页参数,从0开始
				.setSize(15)// 每页条数,默认10
				.addHighlightedField("title")// 设置高亮字段
				.setHighlighterPreTags("<em>")// 设置高亮前缀
				.setHighlighterPostTags("</em>")// 设置高亮后缀
				.get();
		SearchHits hits = searchResponse.getHits();// 命中
		System.out.println("命中条数" + hits.getTotalHits());
		Map<String, HighlightField> highlightFields;
		HighlightField highlightField;
		Text[] hightTexts;
		Article article;
		ObjectMapper objectMapper = new ObjectMapper();
		for (SearchHit searchHit : hits) {
			// 需要替换高亮部分
			highlightFields = searchHit.getHighlightFields();
			highlightField = highlightFields.get("title");
			hightTexts = highlightField.getFragments();
			String text = "";
			for (Text hightText : hightTexts) {
				text += hightText;
			}
			article = objectMapper.readValue(searchHit.getSourceAsString(), Article.class);
			article.setTitle(text);
			// System.out.println(searchHit.getSource().get("title"));
			System.out.println(article);

		}

	}

	@Autowired
	private ElasticsearchTemplate elasticsearchTemplate;

	@Autowired
	private IArticleDemoRepository articleDemoRepository;

	@Test
	public void send() {
		System.out.println(elasticsearchTemplate);
	}

	@Test
	public void contextLoadsB() throws Exception {
		boolean indexExists = elasticsearchTemplate.indexExists(ArticleDemo.class);
		if (indexExists) {
			System.out.println("索引存在");
		} else {
			System.out.println("创建索引");
			elasticsearchTemplate.createIndex(ArticleDemo.class);
			System.out.println("创建索引成功");
			boolean putMapping = elasticsearchTemplate.putMapping(ArticleDemo.class);
			if (putMapping) {
				System.out.println("创建mapper成功");
			} else {
				System.out.println("mapper存在");
			}
		}
		List<ArticleDemo> arrayList = new ArrayList<ArticleDemo>();
		ArticleDemo article;
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy:mm:dd hh:MM:ss");
		for (int i = 0; i < 300; i++) {
			article = new ArticleDemo();
			article.setAuthor(i + "熊骑士");
			article.setContent(i + "今天基于springboot整合sping-data-elasticserach,学习ES搜索引擎技术及IK分词查询API语法,并简单测试其CRUD API");
			article.setCreateTime(simpleDateFormat.format(new Date()));
			article.setId(i);
			article.setTitle(i + "springboot整合sping-data-elasticserach");
			arrayList.add(article);
		}
		this.articleDemoRepository.save(arrayList);
	}

}
